package edu.stanford.travelhard;

import java.io.File;
import java.util.List;

import edu.stanford.travelhard.ImageAdapter.Order;
import edu.stanford.travelhard.camera.Camera;
import edu.stanford.travelhard.camera.Util;

import android.app.ProgressDialog;
import android.app.TabActivity;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.GridView;
import android.widget.ImageButton;
import android.widget.TabHost;

public class TravelHard extends TabActivity implements AdapterView.OnItemClickListener, View.OnClickListener {
	
	/** Activity codes for spinoffs */
	public static final int ANNOTATE_PHOTO = 0;
	public static final int CAPTURE_PHOTO = 1;
	
	/** Tab indices **/
	private static final int TAB_ALL_MEDIA = 0;
	private static final int TAB_PUBLISHED_MEDIA = 1;
	private static final int TAB_UNPUBLISHED_MEDIA = 2;

	/** Thumbnail dimensions (landscape mode) **/
	private static final int THUMBNAIL_WIDTH = 128;
	private static final int THUMBNAIL_HEIGHT = 96;
	private static final int THUMBNAIL_SAMPLE_SIZE = 20;
	
	private LoadMediaTask mLoadMediaTask;
	private ProgressDialog mLoadMediaProgress;
	
	private TabHost tabHost;
	private GridView mAllView;
	private GridView mPublishedView;
	private GridView mUnpublishedView;
	private ImageAdapter mAllAdapter;
	private ImageAdapter mPublishedAdapter;
	private ImageAdapter mUnpublishedAdapter;
	
	/** Called when the activity is first created. */
    public void onCreate(Bundle savedInstanceState) {
    	Log.i("TRAVELHARD", "onCreate");
    	super.onCreate(savedInstanceState);
        
        setContentView(R.layout.library);
        
        setupTabs();
        
        ImageButton b = (ImageButton) this.findViewById(R.id.new_button);
        b.setOnClickListener(this);
        
        loadMedia();
    }
    
    protected void onDestroy() {
    	Log.i("TRAVELHARD", "onDestroy");
    	super.onDestroy();
    	
    	if (mLoadMediaTask != null && mLoadMediaTask.getStatus() == AsyncTask.Status.RUNNING) {
            mLoadMediaTask.cancel(true);
        }
    	
    	if (mLoadMediaProgress != null) {
    		mLoadMediaProgress.dismiss();
    	}
    	
    	/** free up some memory */
    	mAllAdapter.setItems(null);
    	mAllAdapter = null;
    	mPublishedAdapter.setItems(null);
    	mPublishedAdapter = null;
    	mUnpublishedAdapter.setItems(null);
    	mUnpublishedAdapter = null;
    }
    
    public Object onRetainNonConfigurationInstance() {
    	Log.i("TRAVELHARD", "onRetainNonConfigurationInstance");
    	
    	// if the loader is running, just reload everything later
    	// not ideal, but we'll figure out a fix later
    	if (mLoadMediaTask != null && mLoadMediaTask.getStatus() == AsyncTask.Status.RUNNING) {
    		return null;
    	}
    	
    	// save the bitmaps for later use
    	List<LoadedMedia> loadedMedia = mAllAdapter.getItems();
    	final LoadedMedia[] toRetain = new LoadedMedia[loadedMedia.size()];
    	for (int i = 0; i < toRetain.length; i++) {
    		toRetain[i] = new LoadedMedia(loadedMedia.get(i));
    	}
    	return toRetain;
    }
    
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    	Log.i("TRAVELHARD", "onActivityResult");
    	switch(requestCode){
    	case ANNOTATE_PHOTO:
    	    switch (resultCode) {
    	    case Annotate.RESULT_OK:
    	    	/* no-op */
    	    	break;
    	    case Annotate.RESULT_CANCELED:
    	    	/* no-op */
    	    	break;
    	    case Annotate.RESULT_DELETED:
    	    	try {
    	    		Media m = (Media) data.getExtras().get("media");
    	    		deleteMedia(m);
    	    	} catch (Exception e) {
    	    		e.printStackTrace();
    	    	}
    	    	break;
    	    case Annotate.RESULT_PUBLISHED:
    	    	try {
    	    		Media m = (Media) data.getExtras().get("media");
    	    		setMediaPublished(m);
    	    	} catch (Exception e) {
    	    		e.printStackTrace();
    	    	}
    	    	break;
    	    }
    		break;
    	case CAPTURE_PHOTO:
    		switch (resultCode) {
    		case Camera.RESULT_OK:
    		case Annotate.RESULT_PUBLISHED:
    			try {
    	    		Media m = (Media) data.getExtras().get("media");
    	    		Intent intent = new Intent().setClass(this, Annotate.class);
    	    		intent.putExtra("media", m);
    	    		startActivityForResult(intent, ANNOTATE_PHOTO);
    	    		addMedia(m);
    	    	} catch (Exception e) {
    	    		e.printStackTrace();
    	    	}
    			break;
    		case Camera.RESULT_CANCELED:
    			/* no-op */
    			break;
    		}
    		break;
    	}
    }
	
	private void setupTabs() {
		Log.i("TRAVELHARD", "Setting up tabs");
		
    	// Initialize the tabs
        tabHost = getTabHost(); // The activity TabHost
        TabHost.TabSpec spec;  // Reusable TabSpec for each tab
        
        // Initialize a TabSpec for each tab and add it to the TabHost      
        mAllView = (GridView) this.findViewById(R.id.all_tab); 
        mAllAdapter = new ImageAdapter(this, Order.LAST_CAPTURED);
        mAllView.setAdapter(mAllAdapter);
        mAllView.setOnItemClickListener(this);
        spec = tabHost.newTabSpec("mAllView").setIndicator("All", null);
        spec.setContent(mAllView.getId());
        tabHost.addTab(spec);

        // Do the same for the other tabs
        mPublishedView = (GridView) this.findViewById(R.id.published_tab);
        mPublishedView.setOnItemClickListener(this);
        mPublishedAdapter = new ImageAdapter(this, Order.LAST_PUBLISHED);
        mPublishedView.setAdapter(mPublishedAdapter);
        spec = tabHost.newTabSpec("mPublishedView").setIndicator("Published", null);
        spec.setContent(mPublishedView.getId());
        tabHost.addTab(spec);

        mUnpublishedView = (GridView) this.findViewById(R.id.unpublished_tab);
        mUnpublishedAdapter = new ImageAdapter(this, Order.LAST_CAPTURED);
        mUnpublishedView.setAdapter(mUnpublishedAdapter);
        mUnpublishedView.setOnItemClickListener(this);
        spec = tabHost.newTabSpec("mUnpublishedView").setIndicator("Unpublished", null);
        spec.setContent(mUnpublishedView.getId());
        tabHost.addTab(spec);
    }
    
    private void loadMedia() {
    	Log.i("TRAVELHARD", "Loading media");
    	final Object data = getLastNonConfigurationInstance();
        if (data == null) {
        	Log.i("TRAVELHARD", "Loading media from DB!");
            mLoadMediaTask = (LoadMediaTask) new LoadMediaTask().execute((Media[]) null);
            mLoadMediaProgress = ProgressDialog.show(this, "", "Loading images. Please wait...", true);
        } else {
            final LoadedMedia[] loadedMedia = (LoadedMedia[]) data;
            for (LoadedMedia lm : loadedMedia) {
                addLoadedMedia(lm);
            }
        }
    }
    
    private void addLoadedMedia(LoadedMedia lm) {
    	Log.i("TRAVELHARD", "Adding loaded media");
		mAllAdapter.add(lm);
		if (lm.getMedia().isPublished()) {
			mPublishedAdapter.add(lm);
		} else {
			mUnpublishedAdapter.add(lm);
		}
    }
    
    private void addMedia(Media media) {
    	Log.i("TRAVELHARD", "Adding media");
		mLoadMediaTask = (LoadMediaTask) new LoadMediaTask().execute(media);
		mLoadMediaProgress = ProgressDialog.show(this, "", "Loading image. Please wait...", true);
    }
    
	private void deleteMedia(Media media) {
		Log.i("TRAVELHARD", "Deleting media");
		mAllAdapter.remove(media);
		if (media.isPublished()) {
			mPublishedAdapter.remove(media);
		} else {
			mUnpublishedAdapter.remove(media);
		}
	}
	
	private void setMediaPublished(Media media) throws Exception {
		Log.i("TRAVELHARD", "Setting media published");
		
		// remove the item from the unpublished adapter list
		LoadedMedia item = mUnpublishedAdapter.remove(media);
		
		// set the item's media published time
		// these are separate media objects, so
		// it's necessary to do this (though
		// maybe there's a better solution?)
		item.getMedia().setTimePublished(media.getTimePublished());
		mPublishedAdapter.add(item);
		tabHost.setCurrentTab(TAB_PUBLISHED_MEDIA);
	}
	
	public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
		final Intent intent = new Intent().setClass(TravelHard.this, Annotate.class);
		Media m = ((LoadedMedia) parent.getItemAtPosition(position)).getMedia();
		intent.putExtra("media", m);
		startActivityForResult(intent, ANNOTATE_PHOTO);
	}

	public void onClick(View v) {
		final Intent intent = new Intent().setClass(this, Camera.class);
		startActivityForResult(intent, CAPTURE_PHOTO);
	}
	
	private class LoadMediaTask extends AsyncTask<Media, LoadedMedia, Void> {
		
		protected Void doInBackground(Media... mediaArray) {
			int size = 0;
			List<Media> mediaList = null;
			
			// want to be able to do DB lookup in background
			// cause we don't want to hang the UI thread
			// so we do this stupid array/list hack
			if (mediaArray == null) {
				DatabaseHelper dbh = TravelCore.getDBH();
				dbh.open();
				mediaList = dbh.selectAll();
				dbh.close();
				size = mediaList.size();
			} else {
				size = mediaArray.length;
			}
			
			for (int i = 0; i < size; i++) {
				if (isCancelled()) break;
				
				// hack hack hack
				Media m;
				if (mediaArray == null) {
					m = mediaList.get(i);
				} else {
					m = mediaArray[i];
				}
				
				Bitmap b = null;
				String filename = m.getPhotoFilename();
				File file = new File(filename);
				if (file.exists()) {
					b = Util.makeBitmap(file, m.getPhotoOrientation(),
							THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT,
							THUMBNAIL_SAMPLE_SIZE);
					if (!isCancelled()) publishProgress(new LoadedMedia(m, b));
				}
			}
			return null;
		}
		
		protected void onProgressUpdate(LoadedMedia... lm) {
			addLoadedMedia(lm[0]);
		}
		
		protected void onPostExecute(Void result) {
			mLoadMediaTask = null;
			mLoadMediaProgress.dismiss();
			mLoadMediaProgress = null;
		}
	}
}